package net.repchain.browser.common;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.JsonFormat;
import com.rcjava.protos.Peer;
import net.repchain.browser.common.config.ServiceException;
import net.repchain.browser.dao.RepchainBlockDao;
import net.repchain.browser.dao.RepchainTransactionDao;
import net.repchain.browser.entity.RepchainBlock;
import net.repchain.browser.entity.RepchainTransaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;

import java.time.Instant;
import java.util.*;

/**
 * @author lhc
 * @version 1.0
 * @className BlockSyncServiceImpl
 * @date 2021年07月08日 11:41 上午
 * @description 描述
 */
@Service
public class BlockSyncServiceImpl implements BlockSyncService {

    private final Logger logger = LoggerFactory.getLogger(BlockSyncServiceImpl.class);


    final RepchainConfig repchainConfig;
    final RepchainBlockDao repchainBlockDao;
    final RepchainTransactionDao repchainTransactionDao;
    public BlockSyncServiceImpl(RepchainConfig repchainConfig, RepchainBlockDao repchainBlockDao,
                                RepchainTransactionDao repchainTransactionDao) {
        this.repchainConfig = repchainConfig;
        this.repchainBlockDao = repchainBlockDao;
        this.repchainTransactionDao = repchainTransactionDao;
    }

    public Date ts2Instant(Timestamp ts) {
        System.out.print(ts.toString());
        return Date.from(Instant.ofEpochSecond(ts.getSeconds() - 8 * 3600, ts.getNanos()));
    }

    @Override
    public void saveBlock(Peer.Block block) throws InvalidProtocolBufferException {
        logger.info("同步区块成功，区块高度为：{}，开始数据库相关操作", block.getHeader().getHeight());
        RepchainBlock repchainBlock = new RepchainBlock();
        repchainBlock.setBlockCreateTime(ts2Instant(block.getHeader().getEndorsements(0).getTmLocal()));
        repchainBlock.setBlockHashBase(Base64Utils.encodeToString(block.getHeader().getHashPresent().toByteArray()));
        repchainBlock.setBlockHeight(block.getHeader().getHeight());
        repchainBlock.setBlockHash(block.getHeader().getHashPresent().toStringUtf8());
        repchainBlock.setBlockJson(JsonFormat.printer().print(block));
        if (repchainBlockDao.selectCount(RepchainBlock.builder().blockHeight(block.getHeader().getHeight()).build()) == 0) {
            int i = repchainBlockDao.insert(repchainBlock);
            if (i < 1) {
                throw new ServiceException("区块保存失败");
            } else {
                logger.info("区块：{} 保存成功", block.getHeader().getHeight());
            }
        }
        HashMap<String, Peer.TransactionResult> transactionResultMap = new HashMap<>();
        for (Peer.TransactionResult tr : block.getTransactionResultsList()) {
            transactionResultMap.put(tr.getTxId(), tr);
        }
        // 更新transaction表
        for (Peer.Transaction tran : block.getTransactionsList()) {
            if (repchainTransactionDao.selectCount(RepchainTransaction.builder().txId(tran.getId()).build()) == 0) {
                RepchainTransaction repchainTransaction = RepchainTransaction
                        .builder()
                        .transactionJson(JsonFormat.printer().print(tran))
                        .blockHash( block.getHeader().getHashPresent().toStringUtf8())
                        .transactionResult( JsonFormat.printer().print(transactionResultMap.get(tran.getId())))
                        .createTime(ts2Instant(block.getHeader().getEndorsements(0).getTmLocal()))
                        .signatureCreditCode(tran.getSignature().getCertId().getCreditCode())
                        .txId(tran.getId())
                        .blockHeight(block.getHeader().getHeight())
                        .build();
                int i = repchainTransactionDao.insert(repchainTransaction);
                if (i < 1) {
                    throw new ServiceException("交易保存失败");
                } else {
                    logger.info("交易：{} 保存成功", tran.getId());
                }
            }
        }
    }
}
